Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Conversation

@cheme
Copy link
Contributor

@cheme cheme commented Jun 22, 2020

This PR restrict Protected types to some heap types.
The goal is to avoid wrongly using Protected over some structure on stack.
I think this should be enough for current usage, going further will probably lead to write https://github.com/iqlusioninc/crates/tree/develop/secrecy .

@cheme cheme added A0-please_review Pull request needs code review. C1-low PR touches the given topic and has a low impact on builders. B2-breaksapi labels Jun 22, 2020
@cheme cheme requested a review from tomusdrw June 22, 2020 16:21
@cheme cheme requested a review from NikVolf as a code owner June 22, 2020 16:21
impl<T: Zeroize> From<T> for Protected<T> {
fn from(t: T) -> Self {
#[cfg(feature = "std")]
impl From<String> for Protected<String> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not just open this From<T: Zeroize>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is with type as [u8; N] where zeroize is implemented but for whom Protected would be moving/copying stack memory all around. Typically String and Vec are relatively safe to use (as long as we don't reallocate), otherwhise Box would be safe but the api change a bit for it.
Then it does not change a thing with existing code, it just prevents some misuses.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Protected does not implement Copy.

Next point is that you can not implement Drop for Copyable types: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ffa7796c63f95857904cdce1e0a3ebc5

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more refering to moves or memory copy of the stack that result from compiling. But the PR just move this case out to avoid such discussion on the public api.
Another way to handle this could be to add a comment.

Copy link
Contributor

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks okay, but really requires a bit of explanations in comments on why we restrict the From implementation.

Why not do Protected<T>(Box<T>) instead? So that we are not restricted to heap-allocated types?

@tomusdrw tomusdrw added A5-grumble and removed A0-please_review Pull request needs code review. labels Jun 23, 2020
@cheme
Copy link
Contributor Author

cheme commented Jun 23, 2020

I had a first implementation with Box but I remember some slight api difference (at least for the sized array case) and did add a new structure for the Box case. Actually looking at 'secrecy' crate from the author of zeroize, that is exactly the three cases that get covered (box, vec and string).
Knowing myself I probably looked at the only usage being Protected<Box> and felt like it was not ok (on a different branch I simply switch Protected to a struct ProtectedString but it was way bigger diff overall).
So at this point, I did drop the box code, I think we are using this 'simple' Protected, Protected is identic code, but Protected<Box> would be adding new code, so if the need arise for it we should ask if we should use Secrecy crate (Protected for the current use looks lighter than a new dependency).
Will be adding some doc.

@burdges
Copy link

burdges commented Jun 23, 2020

I think the secrecy crate serves mostly as reminder and grep fodder for whenever you access a secret. Use it directly maybe?

I'd wait for rust-lang/rfcs#2859 myself before doing anything else.

I think heap vs stack remains unconvincing without further effort, ala mlock, which all sounds like a distraction now. We've an Arc in the key store which helps avoid keys being cloned much, but obviously a Box does nothing against clone, and Vec even less.

@cheme
Copy link
Contributor Author

cheme commented Jun 23, 2020

Use it directly maybe?

I consider that, honestly it will not be to much work to replace Protected by Secrecy, but I step back because I was not sure that having to follow a new crate code was worth it. cc @tomusdrw @bkchr what do you think?

@tomusdrw
Copy link
Contributor

I'm fine to use secrecy, the crate is pretty small (you can check the code in like 5 mins). AFAICT the point was that due to rust move semantics, stack-allocated secrets will remain in memory (drop is not being called when you move the value, but the value actually is copied), hence we want to make sure that whatever is Protected is heap-allocated, so that when Protected value is moved around only the memory pointer is being copied. And secrecy doesn't really have anything that supports this pattern, so we would need to wrap it or document correctly to make sure it's used correctly.

@burdges
Copy link

burdges commented Jun 23, 2020

Yes, I suppose more discipline in how substrate handles secrets makes sense.

All rust crypto crates use almost exclusively stack for secrets. I doubt any would change this until rust-lang/rfcs#2859 and rust-lang/rfcs#2884 works, and maybe someone needs to figure out mlock from rust too, so optimistically a couple years away. It's rather a different problem in substrate though, so sure..

@cheme cheme requested a review from cecton as a code owner June 23, 2020 10:51
@cheme
Copy link
Contributor Author

cheme commented Jun 23, 2020

Last commit simply replace Protected by SecrecyString.

@PoignardAzur
Copy link

I'd wait for rust-lang/rfcs#2859 myself before doing anything else.

RFC co-author here.

I'm probably not saying anything you don't already know, but I just want to point out that the RFC is dead in the water so far. The lang team hasn't shown any interest yet (that might change with the new MCP process, but I'm skeptical), and until they do there isn't even a guarantee that the RFC will be officialized as something we want in Rust.

So "a couple years away" is indeed optimistic.

Copy link
Contributor

@cecton cecton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is great! But maybe it's best to wait for other reviewers

impl Drop for KeystoreParams {
fn drop(&mut self) {
use sp_core::crypto::Zeroize;
self.password.zeroize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not replace password: Option<StringSecret> to remove this custom implementation of Drop here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It implements FromStr, but structopt complain about to_string not being implemented. Could use a type wrapper, but I am not sure it is worth it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, it is actually the from str error that needed to be display, so no pb.

#[doc(hidden)]
pub use sp_std::ops::Deref;
use sp_runtime_interface::pass_by::PassByInner;
#[doc(hidden)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are both of these exported hidden?

@cheme
Copy link
Contributor Author

cheme commented Jun 30, 2020

@bkchr I did remove the drop on the struct opt parameter, looks better now.

Copy link
Member

@bkchr bkchr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename and move the secret string parse function. Otherwise it looks good.

Comment on lines 51 to 56
#[cfg(feature = "std")]
/// Parse a sercret string, returning a displayable error.
pub fn secrety_string_from_str(s: &str) -> Result<SecretString, String> {
Ok(std::str::FromStr::from_str(s)
.map_err(|_e| "Could not get SecretString".to_string())?)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[cfg(feature = "std")]
/// Parse a sercret string, returning a displayable error.
pub fn secrety_string_from_str(s: &str) -> Result<SecretString, String> {
Ok(std::str::FromStr::from_str(s)
.map_err(|_e| "Could not get SecretString".to_string())?)
}
/// Parse a sercret string, returning a displayable error.
#[cfg(feature = "std")]
pub fn secret_string_from_str(s: &str) -> Result<SecretString, String> {
std::str::FromStr::from_str(s).map_err(|_e| "Could not get SecretString".to_string())
}

And please move this to cli. As we only need this in the cli. Please put it into client/cli/src/params/mod.rs.

@bkchr
Copy link
Member

bkchr commented Jul 1, 2020

bot merge

@ghost
Copy link

ghost commented Jul 1, 2020

Waiting for commit status...

@ghost
Copy link

ghost commented Jul 1, 2020

Head SHA has changed since merge was requested; aborting merge.

2 similar comments
@ghost
Copy link

ghost commented Jul 1, 2020

Head SHA has changed since merge was requested; aborting merge.

@ghost
Copy link

ghost commented Jul 1, 2020

Head SHA has changed since merge was requested; aborting merge.

@bkchr
Copy link
Member

bkchr commented Jul 1, 2020

bot merge

@ghost
Copy link

ghost commented Jul 1, 2020

Waiting for commit status...

@gavofyork
Copy link
Member

@cheme will need a master-merge in order to fix cargo-deny error.

@ghost
Copy link

ghost commented Jul 1, 2020

Head SHA has changed since merge was requested; aborting merge.

@cheme
Copy link
Contributor Author

cheme commented Jul 1, 2020

bot merge

@ghost
Copy link

ghost commented Jul 1, 2020

Waiting for commit status...

@ghost ghost merged commit 8ef1ac0 into paritytech:master Jul 1, 2020
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

C1-low PR touches the given topic and has a low impact on builders.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants